package de.jmda.gen.java.impl;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import de.jmda.gen.Generator;
import de.jmda.gen.GeneratorException;
import de.jmda.gen.impl.AbstractCompoundGenerator;
import de.jmda.gen.java.ImportStatementGenerator;
import de.jmda.gen.java.ImportStatementsGenerator;

/**
 * Maintains a list of {@link ImportStatementGenerator}s.
 *
 * @author rwegner
 */
public class DefaultImportStatementsGenerator
		extends AbstractCompoundGenerator
		implements ImportStatementsGenerator
{
	private List<ImportStatementGenerator> importStatementGenerators;

	public DefaultImportStatementsGenerator()
  {
	  super();

	  setImportStatementGenerators(new ArrayList<ImportStatementGenerator>());

	  setComponentSeparator(System.lineSeparator());
  }

	/**
	 * Returns collection of <code>Generator</code>s with the return values of the
	 * following methods in the following order:
	 * <ul>
	 *   <li>{@link #getImportStatementGenerators()}</li>
	 * </ul>
	 * 
	 * @see de.jmda.gen.CompoundGenerator#getGeneratorComponents()
	 */
	@Override
  public List<Generator> getGeneratorComponents()
  {
		// copy specific generators to non-specific generators and make Java happy
		List<Generator> result = new LinkedList<Generator>();
		
		result.addAll(getImportStatementGenerators());

		return result;
  }

	/**
	 * @see de.jmda.gen.java.ImportStatementsGenerator#getImportStatementGenerators()
	 */
	@Override
  public List<ImportStatementGenerator> getImportStatementGenerators()
  {
		return importStatementGenerators;
  }

	public void setImportStatementGenerators(
      List<ImportStatementGenerator> importStatementGenerators)
  {
		if (importStatementGenerators == null)
		{
			return;
		}

		this.importStatementGenerators = importStatementGenerators;
  }

	/**
	 * Convenience method to add an <code>ImportStatementGenerator</code> to
	 * {@link #getImportStatementGenerators()}.
	 *
	 * @param importStatementGenerator
	 */
	public void add(ImportStatementGenerator importStatementGenerator)
	{
		getImportStatementGenerators().add(importStatementGenerator);
	}

	@Override
  public StringBuffer generate() throws GeneratorException
  {
	  return validate(super.generate());
  }
	
	/**
	 * @param input
	 * @return input
	 * @throws GeneratorException if compound generators produce multiple
	 *         identical import statements
	 */
	protected StringBuffer validate(StringBuffer input) throws GeneratorException
	{
		for (ImportStatementGenerator generator : getImportStatementGenerators())
		{
			String importStatement = generator.generate().toString();
			
			if (StringUtils.countMatches(input.toString(), importStatement) > 1)
			{
				throw new GeneratorException(
						"multiple occurence of identical import statement " +
						"[" + importStatement + "]");
			}
		}
		
		return input;
	}
}